﻿using FlyingCircusWebIS.Controllers.Utilidades;
using FlyingCircusWebIS.Filtros;
using FlyingCircusWebIS.Models;
using FlyingCircusWebIS.ViewModels.VooVM;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PagedList;
using Microsoft.Reporting.WebForms;
using System.IO;
using FlyingCircusWebIS.Relatorios;


namespace FlyingCircusWebIS.Controllers
{
    [AutenticacaoFilter("A")]
    public class VooController : Controller
    {
        private IVooService vooService;
        private ICidadeService cidadeService;
        private IAeroportoService aeroportoService;
        private IAeronaveService aeronaveService;
        private IReservaService reservaService;
        private IPessoaService pessoaService;

        public VooController()
        {
            vooService = new VooService();
            cidadeService = new CidadeService();
            aeroportoService = new AeroportoService();
            aeronaveService = new AeronaveService();
            reservaService = new ReservaService();
            pessoaService = new PessoaService();
        }

        public ActionResult Index(int pagina = 1, string localPartida = "", string localChegada = "", string idAeronave = "", bool filtroPorIdPessoaUsuario = false)
        {
            VooIndexVM vm = ConstruirIndexVM(pagina, localPartida, localChegada, idAeronave, filtroPorIdPessoaUsuario);
            return View(vm);
        }

        public ActionResult Cadastrar(int? id)
        {
            VooCadastrarVM vm;

            if (id.HasValue)
            {
                vm = ConstruirFormVMParaEdicao(id.Value);
                if (vm == null)
                    return new HttpNotFoundResult();
            }
            else
            {
                vm = ConstruirFormVMParaNovo();
            }

            return View(vm);
        }

        [HttpPost]
        public ActionResult Cadastrar(VooCadastrarVM vm)
        {
            if (ModelState.IsValid)
            {
                Voo registro = ConverterFormVM(vm);

                List<ValidationResult> erros = vooService.ValidarEntidade(registro);

                if (erros.Count == 0)
                {
                    if (vm.Edicao)
                        vooService.Atualizar(registro);
                    else
                        vooService.Adicionar(registro);

                    return RedirectToAction("Index");
                }
                else
                {
                    ModelState.AddModelErrors(erros);
                }
            }

            PopularItensCadastrarVM(vm);

            return View(vm);
        }

        public ActionResult GerarRelatorioOcupacao(int idVoo, string tipo = "PDF")
        {
            string nomeExtensaoArquivo;
            string mimeType;

            byte[] bytes = GeradorRelatorios.GerarRelatorioOcupacao(idVoo, tipo, Server, out nomeExtensaoArquivo, out mimeType);

            string nomeArquivo = "rela_ocup_" + DateTime.Now.ToShortDateString() + ".";
            return File(bytes, mimeType, nomeArquivo + nomeExtensaoArquivo);
        }

        public ActionResult Passageiros(int id)
        {
            VooPassageirosVM vm = new VooPassageirosVM();
            vm.IdVoo = id;

            vm.voo = vooService.BuscarPorId(id);
            vm.reservas= reservaService.ListarReservasDoVoo(id);

            return View(vm);
        }

        public JsonResult BuscarItensCidades(string uf)
        {
            var itens = cidadeService.ListarItensCidadesAeroportosPorUF(uf);
            return Json(itens, JsonRequestBehavior.AllowGet);
        }

        public JsonResult BuscarItensAeroportosPorCidade(int id)
        {
            var itens = aeroportoService.ListarItensAeroportosPorIdCidade(id);
            return Json(itens, JsonRequestBehavior.AllowGet);
        }

        public JsonResult BuscarItensAeronavesPorDatas(string dataPartida, string dataChegada, int idVoo, bool edicao)
        {
            JsonActionResultModel jarm = new JsonActionResultModel();
            List<ValidationResult> erros = vooService.ValidarData(dataPartida);
            erros.AddRange(vooService.ValidarData(dataChegada));

            if (erros.Count == 0)
            {
                List<SelectListItem> itens;
                if (edicao)
                {
                    int idAeronave = vooService.Listar().Find(vo => vo.IdVoo == idVoo).IdAeronave;
                    itens = aeronaveService.ListarItensAeronaveFormatado().FindAll(ae => ae.Value == idAeronave.ToString());
                    itens.AddRange(vooService.ListarItensAeronavesDisponiveis(DateTime.Parse(dataPartida), DateTime.Parse(dataChegada)));
                }
                else
                {
                    itens = vooService.ListarItensAeronavesDisponiveis(DateTime.Parse(dataPartida), DateTime.Parse(dataChegada));
                }

                return Json(itens, JsonRequestBehavior.AllowGet);
            }
            else
            {
                ModelState.AddModelErrors(erros);
                return Json(jarm);
            }
        }

        public JsonResult Remover(int id)
        {
            JsonActionResultModel jarm = new JsonActionResultModel();
            var erros = vooService.ValidaRemoverPorId(id);
            if (erros.Count == 0)
            {
                vooService.RemoverPorId(id);
                jarm.Erro = false;
                jarm.Mensagem = "Registro removido com sucesso";
            }
            else
            {
                jarm.Erro = true;
                jarm.Mensagem = "Não é possível remover o registro.\n";
                jarm.AddValidationResultErros(erros);
            }

            return Json(jarm);
        }

        // -----------------------------------------------------------------------------------------
        // Métodos auxiliares 
        // -----------------------------------------------------------------------------------------

        private void PopularItensCadastrarVM(VooCadastrarVM vm)
        {
            vm.ItensUFPartida = cidadeService.ListarItensUF();
            string uf = vm.UFPartida;
            if (!String.IsNullOrEmpty(uf))
                vm.ItensCidadePartida = cidadeService.ListarItensCidadesAeroportosPorUF(vm.UFPartida);
            else
                vm.ItensCidadePartida = cidadeService.ListarItensCidadesParaNovo();

            string idCidade = vm.CidadePartida;
            if (!String.IsNullOrEmpty(idCidade))
                vm.ItensAeroportoPartida = aeroportoService.ListarItensAeroportosPorIdCidade(int.Parse(idCidade));
            else
                vm.ItensAeroportoPartida = aeroportoService.ListarItensAeroportosParaNovo();

            vm.ItensUFChegada = cidadeService.ListarItensUF();

            uf = vm.UFChegada;
            if (!String.IsNullOrEmpty(uf))
                vm.ItensCidadeChegada = cidadeService.ListarItensCidadesAeroportosPorUF(vm.UFChegada);
            else
                vm.ItensCidadeChegada = cidadeService.ListarItensCidadesParaNovo();

            idCidade = vm.CidadeChegada;
            if (!String.IsNullOrEmpty(idCidade))
                vm.ItensAeroportoChegada = aeroportoService.ListarItensAeroportosPorIdCidade(int.Parse(vm.CidadeChegada));
            else
                vm.ItensAeroportoChegada = aeroportoService.ListarItensAeroportosParaNovo();

            if (vm.Edicao && !String.IsNullOrEmpty(vm.DataPartida) && !String.IsNullOrEmpty(vm.DataCadastro))
            {
                //Busca as aeronaves disponiveis e adiciona a que já está cadastrada no Voo como uma opção
                vm.ItensAeronaves = aeronaveService.ListarItensAeronaveFormatado().FindAll(ae => ae.Value == vm.IdAeronave);

                List<SelectListItem> aeronavesDisponiveis = vooService.ListarItensAeronavesDisponiveis(DateTime.Parse(vm.DataPartida), DateTime.Parse(vm.DataChegada));
                if (aeronavesDisponiveis.Count > 0 && !aeronavesDisponiveis.Any(m => m.Value == ""))
                    vm.ItensAeronaves.AddRange(aeronavesDisponiveis);
            }
            else
            {
                vm.ItensAeronaves = aeronaveService.ListarItensAeronavesParaNovo();
            }
        }

        private VooIndexVM ConstruirIndexVM(int pagina, string localPartida, string localChegada, string idAeronave, bool filtroPorIdPessoaUsuario)
        {
            string idPessoaUsuario = filtroPorIdPessoaUsuario ? ((Pessoa)Session["usuario"]).IdPessoa.ToString() : "";
            var registros = vooService.ListarVoosFiltro(localPartida, localChegada, idAeronave, idPessoaUsuario).ToPagedList(pagina, 15);

            VooIndexVM vm = new VooIndexVM();
            vm.Registros = registros;
            vm.TotalRegistros = registros.Count;
            vm.LocalPartida = localPartida;
            vm.LocalChegada = localChegada;
            vm.ItensAeronaves = aeronaveService.ListarItensAeronaveFormatadoParaFiltro();
            vm.IdAeronave = idAeronave;
            vm.FiltroPorIdPessoaUsuario = filtroPorIdPessoaUsuario;

            List<Tuple<int, int>> lista = new List<Tuple<int, int>>();
            foreach (var voo in vm.Registros)
            {
                var reservas = vooService.TotalReservasParaVoo(voo.IdVoo);

                Tuple<int, int> tuplaIdVooReservas = new Tuple<int, int>(voo.IdVoo, reservas);
                lista.Add(tuplaIdVooReservas);
            }

            vm.TuplasIdVooQtdReservas = lista;
            //vm.ListaReservas = reservaService.Listar();
            return vm;
        }

        private VooCadastrarVM ConstruirFormVMParaNovo()
        {
            VooCadastrarVM vm = new VooCadastrarVM();
            vm.Edicao = false;

            vm.ItensUFPartida = cidadeService.ListarItensUF();
            vm.ItensCidadePartida = cidadeService.ListarItensCidadesParaNovo();
            vm.ItensAeroportoPartida = aeroportoService.ListarItensAeroportosParaNovo();

            vm.ItensUFChegada = cidadeService.ListarItensUF();
            vm.ItensCidadeChegada = cidadeService.ListarItensCidadesParaNovo();
            vm.ItensAeroportoChegada = aeroportoService.ListarItensAeroportosParaNovo();

            vm.ItensAeronaves = aeronaveService.ListarItensAeronavesParaNovo();

            vm.IdPessoaUsuario = ((Pessoa)Session["usuario"]).IdPessoa;

            return vm;
        }

        private VooCadastrarVM ConstruirFormVMParaEdicao(int id)
        {
            Voo registro = vooService.BuscarPorId(id);
            if (registro != null)
            {
                int idAeroportoPartida = registro.IdAeroportoPartida;
                int idCidadePartida = aeroportoService.BuscarPorId(idAeroportoPartida).IdCidade;
                string UFPartida = cidadeService.BuscarUFCidadePorId(idCidadePartida);

                int idAeroportoChegada = registro.IdAeroportoChegada;
                int idCidadeChegada = aeroportoService.BuscarPorId(idAeroportoChegada).IdCidade;
                string UFChegada = cidadeService.BuscarUFCidadePorId(idCidadeChegada);

                VooCadastrarVM vm = ConverterFormVM(registro);

                vm.UFPartida = UFPartida;
                vm.ItensUFPartida = cidadeService.ListarItensUF();
                vm.ItensCidadePartida = cidadeService.ListarItensCidadesAeroportosPorUF(UFPartida);
                vm.ItensAeroportoPartida = aeroportoService.ListarItensAeroportosPorIdCidade(idCidadePartida);
                vm.DataPartida = registro.DataPartida.ToString("dd\"/\"MM\"/\"yyyy HH:mm");

                vm.UFChegada = UFChegada;
                vm.ItensUFChegada = cidadeService.ListarItensUF();
                vm.ItensCidadeChegada = cidadeService.ListarItensCidadesAeroportosPorUF(UFChegada);
                vm.ItensAeroportoChegada = aeroportoService.ListarItensAeroportosPorIdCidade(idCidadeChegada);
                vm.DataChegada = registro.DataChegada.ToString("dd\"/\"MM\"/\"yyyy HH:mm");

                vm.IdPessoaUsuario = ((Pessoa)Session["usuario"]).IdPessoa;
                vm.IdVoo = id;

                //Busca as aeronaves disponiveis e adiciona a que já está cadastrada no Voo como uma opção
                vm.IdAeronave = registro.IdAeronave.ToString();
                vm.ItensAeronaves = aeronaveService.ListarItensAeronaveFormatado().FindAll(ae => ae.Value == vm.IdAeronave);

                List<SelectListItem> aeronavesDisponiveis = vooService.ListarItensAeronavesDisponiveis(registro.DataPartida, registro.DataChegada);
                if (aeronavesDisponiveis.Count > 0 && !aeronavesDisponiveis.Any(m => m.Value == ""))
                    vm.ItensAeronaves.AddRange(aeronavesDisponiveis);

                vm.AssentosComercializaveis = registro.AssentosComercializaveis.ToString();
                vm.VooPromocional = registro.VooPromocional == "S";
                vm.DescontoPromocao = (registro.DescontoPromocao.Value * 100).ToString("N2");
                vm.Lucro = (registro.Lucro * 100).ToString("N2");
                vm.Preco = registro.PrecoVoo.ToString("N2");

                vm.Edicao = true;

                return vm;
            }

            return null;
        }

        private Voo ConverterFormVM(VooCadastrarVM vm)
        {
            Voo registro = new Voo();

            registro.IdPessoaUsuario = vm.IdPessoaUsuario;
            registro.IdVoo = vm.IdVoo;
            registro.IdAeronave = vm.IdAeronave != null ? int.Parse(vm.IdAeronave) : 0;
            registro.AssentosComercializaveis = vm.AssentosComercializaveis != "" ? int.Parse(vm.AssentosComercializaveis) : 0;

            registro.DataPartida = DateTime.Parse(vm.DataPartida);
            registro.IdAeroportoPartida = vm.AeroportoPartida != "" ? int.Parse(vm.AeroportoPartida) : 0;

            registro.DataChegada = DateTime.Parse(vm.DataChegada);
            registro.IdAeroportoChegada = vm.AeroportoChegada != "" ? int.Parse(vm.AeroportoChegada) : 0;

            registro.DataCadastro = DateTime.Now;
            registro.Lucro = Decimal.Parse(vm.Lucro)/100;
            registro.PrecoVoo = Decimal.Parse(vm.Preco);
            registro.VooPromocional = vm.VooPromocional ? "S" : "N";
            registro.DescontoPromocao = vm.DescontoPromocao != null ? Decimal.Parse(vm.DescontoPromocao)/100 : 0;

            return registro;
        }

        private VooCadastrarVM ConverterFormVM(Voo entidade)
        {
            VooCadastrarVM vm = new VooCadastrarVM();

            vm.IdVoo = entidade.IdVoo;
            vm.IdPessoaUsuario = entidade.IdPessoaUsuario;
            vm.AeroportoChegada = entidade.IdAeroportoChegada.ToString();
            vm.AeroportoPartida = entidade.IdAeroportoPartida.ToString();
            vm.AssentosComercializaveis = entidade.AssentosComercializaveis.ToString();
            vm.CidadeChegada = aeroportoService.BuscarPorId(entidade.IdAeroportoChegada).IdCidade.ToString();
            vm.CidadePartida = aeroportoService.BuscarPorId(entidade.IdAeroportoPartida).IdCidade.ToString();
            vm.DataChegada = entidade.DataChegada.ToString("dd\"/\"MM\"/\"yyyy HH:mm");
            vm.DataPartida = entidade.DataPartida.ToString("dd\"/\"MM\"/\"yyyy HH:mm");
            vm.DescontoPromocao = entidade.DescontoPromocao.ToString();
            vm.IdAeronave = entidade.IdAeronave.ToString();

            vm.Preco = entidade.PrecoVoo.ToString();
            vm.UFChegada = cidadeService.BuscarUFCidadePorId(aeroportoService.BuscarPorId(entidade.IdAeroportoChegada).IdCidade);
            vm.UFPartida = cidadeService.BuscarUFCidadePorId(aeroportoService.BuscarPorId(entidade.IdAeroportoPartida).IdCidade);
            vm.VooPromocional = entidade.VooPromocional == "S";

            return vm;
        }
    }
}
